{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "        gcvs      +       /\n",
      "M     9140.0    6.0     0.0\n",
      "RRAB  7144.0    0.0     0.0\n",
      "EA    4054.0  103.0  1645.0\n",
      "LB    3950.0    1.0     0.0\n",
      "EW    3463.0    4.0   344.0\n",
      "SR    3181.0    7.0     0.0\n",
      "SRB   2839.0    0.0     0.0\n",
      "RRC   1674.0    0.0     0.0\n",
      "RR    1631.0    0.0     0.0\n",
      "EB    1415.0    6.0   302.0\n"
     ]
    }
   ],
   "source": [
    "\"\"\"Script for plotting a bar chart with types of variable stars in\n",
    "the current version of the General Catalog of Variable Stars (GCVS).\n",
    "Data source: http://www.sai.msu.su/gcvs/gcvs/gcvs5/gcvs5.txt\n",
    "\n",
    "According to GCVS Variability Types description,\n",
    "http://www.sai.msu.su/gcvs/gcvs/vartype.htm\n",
    "if a variable belongs to several types of variability, the types are joined\n",
    "in the data field by a \"+\" sign, e.g., E+UG, UV+BY.\n",
    "Multiple classifications for object types are separated by a solidus (\"/\").\n",
    "We collect them separatly in additional data arrays.\n",
    "Uncertainty on type of variability marked with a colon (:) is discarded for simplicity.\n",
    "\"\"\"\n",
    "\n",
    "\n",
    "import os\n",
    "\n",
    "from scour import scour\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.ticker import MultipleLocator\n",
    "import pandas as pd\n",
    "\n",
    "\n",
    "def optimize_svg(tmp_path, path):\n",
    "    \"\"\"Optimize svg file using scour\"\"\"\n",
    "    with open(tmp_path, \"rb\") as inputfile, open(path, \"wb\") as outputfile:\n",
    "        options = scour.generateDefaultOptions()\n",
    "        options.enable_viewboxing = True\n",
    "        options.strip_comments = True\n",
    "        options.strip_ids = True\n",
    "        options.remove_metadata = True\n",
    "        options.shorten_ids = True\n",
    "        options.indent_type = \"none\"\n",
    "        options.newlines = False\n",
    "        scour.start(options, inputfile, outputfile)\n",
    "\n",
    "\n",
    "def fill_dct(dct, typ):\n",
    "    \"\"\"Fill dictionary with given type name.\"\"\"\n",
    "    try:\n",
    "        dct[typ] += 1\n",
    "    except KeyError:\n",
    "        dct[typ] = 1\n",
    "\n",
    "\n",
    "types_dct = {}\n",
    "types_plus = {}\n",
    "types_slash = {}\n",
    "STRIP = True\n",
    "\n",
    "\"\"\"Read GCVS file, get each type of variable star, count them,\n",
    "merge with uncertainly defined types if STRIP == True, collect in dictionaries.\n",
    "\"\"\"\n",
    "with open(\"../../../data/gcvs/gcvs5.txt\", encoding=\"ascii\") as gcvs:\n",
    "    cat = gcvs.readlines()\n",
    "    for line in cat:\n",
    "        typ = line[41:51].strip()\n",
    "        if STRIP:\n",
    "            typ = typ.strip(\":\")\n",
    "        if \"+\" in typ:\n",
    "            for typsplit in typ.split(\"+\"):\n",
    "                if STRIP:\n",
    "                    typsplit = typsplit.strip(\":\")\n",
    "                fill_dct(types_plus, typsplit)\n",
    "        if \"/\" in typ:\n",
    "            for typsplit in typ.split(\"/\"):\n",
    "                if STRIP:\n",
    "                    typsplit = typsplit.strip(\":\")\n",
    "                fill_dct(types_slash, typsplit)\n",
    "        fill_dct(types_dct, typ)\n",
    "\n",
    "NUM = -39\n",
    "df = pd.DataFrame({\n",
    "        \"gcvs\": pd.Series(types_dct),\n",
    "        \"+\": pd.Series(types_plus),\n",
    "        \"/\": pd.Series(types_slash),\n",
    "    }).fillna(0).sort_values(by=\"gcvs\")[NUM:]\n",
    "\n",
    "# print(pd.Series(types_dct).sort_values()[:-5:-1])\n",
    "# print(pd.Series(types_plus).sort_values()[:-5:-1])\n",
    "# print(pd.Series(types_slash).sort_values()[:-5:-1])\n",
    "print(df[:-11:-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ascending=False\n",
    "ax = df.plot.bar(stacked=True, figsize=(16, 9), width=0.88, rot=45)\n",
    "ax.legend([\n",
    "        \"Типы переменных звезд ОКПЗ\",\n",
    "        \"Звезды с несколькими типами переменности (+)\",\n",
    "        \"Компоненты множественных классификаций затменных (/)\",\n",
    "        ], fontsize=12, loc=\"upper left\")\n",
    "\n",
    "plt.subplots_adjust(left=0.051, bottom=0.102, right=0.985, top=0.955)\n",
    "plt.xlabel(\"Типы переменных звезд\", fontsize=14)\n",
    "plt.ylabel(\"Количество переменных звезд\", fontsize=14)\n",
    "plt.title(\"Распределение по типам переменных звезд в текущей версии ОКПЗ, \"\n",
    "    + f\"всего {sum(types_dct.values())} объектов. Октябрь 2022 года\",\n",
    "    fontsize=15)\n",
    "ax.yaxis.set_minor_locator(MultipleLocator(250))\n",
    "for x, y in enumerate(df.sum(axis=1)):\n",
    "    ax.annotate(int(y), (x, y + 42), ha=\"center\")\n",
    "# ax.bar_label(ax.containers[-1])\n",
    "\n",
    "FILE_EXT = \"png\"\n",
    "PLT_PTH = \"../../../plots/stars/gcvs_types_distribution-combined-sorted-latest+\"\n",
    "tmp_pth = f\"{PLT_PTH}_.{FILE_EXT}\"\n",
    "pth = f\"{PLT_PTH}.{FILE_EXT}\"\n",
    "plt.savefig(tmp_pth, dpi=120)\n",
    "if FILE_EXT == \"svg\":\n",
    "    optimize_svg(tmp_pth, pth)\n",
    "    os.remove(tmp_pth)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
